<?php

namespace app\common\service;

use app\common\domain\Warehouse as WarehouseDomain;
use app\common\exception\Client;
use app\common\exception\Server;
use app\common\model\Warehouse as WarehouseModel;
use Exception;
use think\facade\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Cache;
use think\Paginator;
use think\response\Json;

class Warehouse
{
    const CACHE_PREFIX = 'warehouse_active_';

    /**
     * 创建货架服务
     * @param array $params
     * @return array
     * @throws Exception
     */
    public static function createShelf(array $params): array
    {
        // 1. 通过领域层构建数据
        $shelfData = WarehouseDomain::buildShelfData(
            $params['shelfno'],
            $params['total_layers'],
            $params['area']
        );

        $exits = WarehouseModel::where([
            'shelfno' => $params['shelfno'],
            'area' => $params['area'],
        ])->find();
        if($exits) throw new Client(211004,'该区域下'.$params['shelfno'].'号货架已存在');

        try {
            // 2. 通过模型层写入数据库
            $result = (new WarehouseModel())->saveAll($shelfData);
        }catch (Exception $e){
            throw new Server('数据库异常，货架创建失败');
        }
        return [
            'affected_rows' => $result,
            'shelf_data'   => $shelfData
        ];
    }

    /**
     * 新增一个货架层
     * @param $params
     * @return Json
     * @throws Client
     * @throws DbException
     * @throws Server
     */
    public static function createWarehouseLayer($params): Json
    {

        if(WarehouseModel::where([
                'area' => $params['area'],
                'shelfno' => $params['shelfno'],
                'layerno' => $params['layerno']
            ])->count() > 0){
            throw new Client(211004,'该货架层已存在');
        }
        $msg = '货架层创建成功';

        try {
            if($params['is_locked']==0 && WarehouseModel::where([
                    'area' => $params['area'],
                    'is_locked' => 0
                ])->count() > 0){
                $params['is_locked'] = 1;
                $msg = $msg.'，已有其他货架层开启';
            }

            $warehouse = new WarehouseModel();
            $warehouse->save($params);
            $result =  $warehouse->toArray();
            return writeJson(200, $result, $msg);
        }catch (Exception $e){
            throw new Server($e->getMessage());
        }

    }

    /**
     * 批量删除仓库记录
     * @param array $ids ID数组
     * @return bool 删除的记录数
     * @throws Client
     * @throws DbException
     */
    public static function batchDelete(array $ids): bool
    {
        if (empty($ids)) throw new Client(211001,'ID列表不能为空');

        $warehouseModel = new WarehouseModel();
        // 检查所有ID是否存在
        $existsCount = $warehouseModel->where('id','in', $ids)->count();
        if ($existsCount !== count($ids)) throw new Client(211002,'部分记录不存在');

        // 使用事务确保数据一致性
        return $warehouseModel->transaction(function () use ($ids) {
            return WarehouseModel::destroy($ids);
        });
    }

    /**
     * 更新货架层记录
     * @param array $params
     * @return array
     * @throws Client
     * @throws DbException
     * @throws Server
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function update(array $params): array
    {
        //过滤字段
        $warehouseDomain = new WarehouseDomain();
        $data = $warehouseDomain->filterField($params);
        //检查要修改的货架层是否存在
        $warehouseModel = new WarehouseModel();
        $warehouse = $warehouseModel->find($params['id']);
        if (!$warehouse) throw new Client(211001,'货架层不存在');

        // 检查货架位置是否唯一
        if (isset($data['area']) || isset($data['shelfno']) || isset($data['layerno'])) {
            $uniqueCond = $warehouseDomain->getUniqueCond($data,$warehouse);
            $exists = WarehouseModel::where('id', '<>', $params['id'])
                ->where($uniqueCond)
                ->find();
            if ($exists) throw new Client(211001,'货架层已存在');
        }


        Db::startTrans();
        try {
            // 关闭同区域其他开放层（如果要开启当前层）
            if ($data['is_locked'] == 0) {
               WarehouseModel::where(['area'=>$warehouse->area, 'is_locked'=>0 ])
                    ->where('id', '<>', $params['id'])
                    ->update(['is_locked' => 1]);
            }
            // 更新当前层状态
            $warehouse->save($data);
            Db::commit();
            //清楚缓存中已同区域开启的货架层数据
            Cache::rm(self::CACHE_PREFIX . $warehouse->area);
            return $warehouse->toArray();
        } catch (Exception $e) {
            Db::rollback();
            throw new Server($e->getMessage());
        }
    }

    /**
     * 更新当前货架层状态
     * @param int $id
     * @param int $isLocked
     * @return bool
     * @throws Exception
     */
    public static function switchLayerStatus(int $id, int $isLocked): bool
    {
        // 获取目标货架层信息
        $target = (new WarehouseModel())->find($id);
        if (!$target) {
            throw new Client(211002,'货架不存在');
        }
        if($target->is_locked == $isLocked)return true;

        Db::startTrans();
        try {
            // 关闭同区域其他开放层（如果要开启当前层）
            if ($isLocked == 0) {
                WarehouseModel::where(['area'=>$target->area, 'is_locked'=>0 ])
                    ->where('id', '<>', $id)
                    ->update(['is_locked' => 1]);
            }
            // 更新当前层状态
            $target->is_locked = $isLocked;
            $target->save();
            Db::commit();
            Cache::rm(self::CACHE_PREFIX . $target->area);
            return true;
        } catch (Exception $e) {
            Db::rollback();
            throw new Server($e->getMessage());
        }
    }

    /**
     * 获取区域开放货架层（带缓存）
     * @param int $area 区域ID (1:顺丰 2:京东)
     * @return array|bool
     * @throws Exception
     */
    public static function getActiveShelfLayer(int $area)
    {
        try {
            // 1. 尝试从缓存获取
            $cacheKey = self::CACHE_PREFIX . $area;
            $cachedData = Cache::get($cacheKey);
            if (!empty($cachedData)) return $cachedData;

            // 2. 查询数据库
            $activeLayer = (new WarehouseModel())->where([
                'area' => $area,
                'is_locked' => 0
            ])->find();
            if (!$activeLayer) throw new Client(211003,'该区域没有开启的货架');

            // 3. 格式化数据并缓存
            $layerData = WarehouseDomain::formatCacheData($activeLayer);
            Cache::set($cacheKey, $layerData, 7200); // 缓存两小时，时间应该配置在配置文件中
            return $layerData;

        } catch (Exception $e) {
            throw new Server('获取开启的货架层失败：' . $e->getMessage());
        }
    }

    /**
     * 分页查询
     * @param array $params
     * @return Paginator
     */
    public function getPaginatedList(array $params = []): Paginator
    {
        //构建查询条件
        $res = (new WarehouseDomain())->getListCondition($params);
        return (new WarehouseModel())->paginateList(
            $res['where'],
            $res['page'],
            $res['pageSize'],
            $res['order']
        );
    }


}